<?php

namespace Package\RedisHelper\Connection;

use Redis;
use Package\RedisHelper\Config\RedisConfig;
use Package\RedisHelper\Exceptions\RedisConnectionException;

class RedisConnection
{
    protected $redis;
    protected $config;
    protected $isConnected = false;
    
    public function __construct(RedisConfig $config)
    {
        $this->config = $config;
        $this->redis = new Redis();
    }
    
    public function connect(): void
    {
        if ($this->isConnected) {
            return;
        }
        
        try {
            $method = $this->config->isPersistent() ? 'pconnect' : 'connect';
            
            $connected = $this->redis->{$method}(
                $this->config->getHost(),
                $this->config->getPort(),
                $this->config->getTimeout(),
                null, // persistent_id
                $this->config->getRetryInterval(),
                $this->config->getReadTimeout()
            );
            
            if (!$connected) {
                throw new RedisConnectionException("Redis connection failed");
            }
            
            if ($password = $this->config->getPassword()) {
                if (!$this->redis->auth($password)) {
                    throw new RedisConnectionException("Redis authentication failed");
                }
            }
            
            $this->redis->select($this->config->getDatabase());
            
            if ($prefix = $this->config->getPrefix()) {
                $this->redis->setOption(Redis::OPT_PREFIX, $prefix);
            }
            
            $this->redis->setOption(Redis::OPT_SERIALIZER, $this->config->getSerializer());
            
            $this->isConnected = true;
            
        } catch (\RedisException $e) {
            throw new RedisConnectionException("Redis connection error: " . $e->getMessage(), 0, $e);
        }
    }
    
    public function reconnect(): void
    {
        $this->disconnect();
        $this->connect();
    }
    
    public function getRedis(): Redis
    {
        if (!$this->isConnected) {
            $this->connect();
        }
        return $this->redis;
    }
    
    public function disconnect(): void
    {
        if ($this->isConnected && $this->redis instanceof Redis) {
            try {
                $this->redis->close();
            } catch (\RedisException $e) {
                // 记录错误但不中断
                error_log("Redis disconnect error: " . $e->getMessage());
            }
            $this->isConnected = false;
        }
    }
    
    public function isConnected(): bool
    {
        return $this->isConnected;
    }
    
    public function getConfig(): RedisConfig
    {
        return $this->config;
    }
    
    public function __destruct()
    {
        $this->disconnect();
    }
}